package com.fast.develop.integration.context;

import com.fast.develop.core.context.AbstractModuleContext;
import com.fast.develop.core.context.ModuleContext;
import com.fast.develop.core.exception.ModuleContextException;
import com.fast.develop.core.persistence.DomainModelManager;
import com.fast.develop.core.properties.ApiProperties;
import com.fast.develop.core.properties.DomainRuntimeProperties;
import com.fast.develop.core.registry.ModuleRegistry;
import com.fast.develop.integration.HibernateModuleConfiguration;
import com.fast.develop.integration.orm.DomainModelSessionManager;
import com.fast.develop.integration.web.DomainModelResourcesRest;
import com.fast.develop.integration.web.DomainRequestMappingHandlerMapping;
import com.fast.develop.integration.web.MvcMappingHandlerMapping;
import com.fast.develop.meta.base.MetaConfiguration;
import lombok.SneakyThrows;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 莫寅
 * @createTime 2022-06-07 13:22
 * @desc：
 */
public class HibernateModuleContext extends AbstractModuleContext implements ModuleContext {

    Map<Class, Object> beans = new HashMap();

    private MvcMappingHandlerMapping mvcMappingHandlerMapping;
    private DomainRuntimeProperties domainRuntimeProperties;
    private DomainModelResourcesRest domainModelResourcesRest;
    private DomainModelManager domainModelManager;
    private LocalSessionFactoryBean localSessionFactoryBean;
    private DomainRequestMappingHandlerMapping domainRequestMappingHandlerMapping;
    private HibernateModuleConfiguration hibernateModuleConfiguration;

    private boolean enableResourcesRest = false;
    private boolean initialized = false;

    private MetaConfiguration metaConfiguration;


    public HibernateModuleContext(MetaConfiguration metaConfiguration, ModuleRegistry pluginRegistry, HibernateModuleConfiguration hibernateModuleConfiguration, MvcMappingHandlerMapping mvcMappingHandlerMapping) {
        super(metaConfiguration, pluginRegistry);
        this.mvcMappingHandlerMapping = mvcMappingHandlerMapping;
        this.domainRuntimeProperties = hibernateModuleConfiguration.getDomainRuntimeProperties();
        this.localSessionFactoryBean = hibernateModuleConfiguration.getLocalSessionFactoryBean();
        this.enableResourcesRest = hibernateModuleConfiguration.enableResourcesRest();
        this.hibernateModuleConfiguration = hibernateModuleConfiguration;
        this.metaConfiguration = metaConfiguration;
    }



    @Override
    @SneakyThrows
    protected void initialize(){
        if(initialized){
            throw new ModuleContextException("已初始化！");
        }

        enableHibernate();
        initDomainModelManager();
        enableRequestMapping();

        beans.put(DomainRuntimeProperties.class, domainRuntimeProperties);
        beans.put(DomainModelResourcesRest.class, domainModelResourcesRest);
        beans.put(DomainModelManager.class, domainModelManager);
        beans.put(LocalSessionFactoryBean.class, localSessionFactoryBean);
        beans.put(HibernateModuleConfiguration.class, hibernateModuleConfiguration);

        initialized = true;
    }


    @Override
    public void destroy(){
        localSessionFactoryBean.destroy();
        domainRequestMappingHandlerMapping.unRegisterResourcesMapping();
        this.domainModelManager = null;

        super.destroy();
    }

    private void initDomainModelManager(){
        this.domainModelManager = new DomainModelSessionManager(metaConfiguration, localSessionFactoryBean.getObject().openSession());
    }

    private void enableHibernate() throws Exception{
        localSessionFactoryBean.afterPropertiesSet();
    }

    private void enableRequestMapping(){
        if(enableResourcesRest){
            this.domainModelResourcesRest = new DomainModelResourcesRest(domainModelManager);
        }

        ApiProperties apiProperties = new ApiProperties();
        apiProperties.setPrefix(domainRuntimeProperties.getApiPrefix());
        this.domainRequestMappingHandlerMapping = new DomainRequestMappingHandlerMapping(apiProperties, mvcMappingHandlerMapping, domainModelResourcesRest);
        domainRequestMappingHandlerMapping.registerMapping();
    }


    @Override
    public DomainModelManager getDomainModelManager() {
        return domainModelResourcesRest.getdomainModelManager();
    }




}
